/*
 * Copyright (c) 2001 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 *    David Corbin - Add support for creating depot "connections" in all cases
 */
package net.sourceforge.p4eclipse.ui.wizards;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.sourceforge.p4eclipse.core.PerforceRepositoryProvider;
import net.sourceforge.p4eclipse.core.Policy;
import net.sourceforge.p4eclipse.core.api.PerforceServerFactory;
import net.sourceforge.p4eclipse.ui.MicroPluginFactory;
import net.sourceforge.p4eclipse.ui.PerforceUIPlugin;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.ui.IConfigurationWizard;
import org.eclipse.ui.IWorkbench;

/**
  * @version 	1.0
  * @author		<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  * @author		<a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
  */
public class SharingWizard extends Wizard implements IConfigurationWizard
{
	private IProject project;
	private ConnectProjectPage connectProjectPage;	
	
	boolean canConnect = false;

	/**
	 * Constructor for SharingWizard.
	 */
	public SharingWizard()
	{
		setNeedsProgressMonitor(true);
	}
	
	/*
	 * @see IConfigurationWizard#init(IWorkbench, IProject)
	 */
	public void init(IWorkbench workbench, IProject project)
	{
		Policy.assertNotNull(project);		
		this.project = project;
	}
	public boolean canFinish()
	{
//		if (! connectProjectPage.canFinish())
//			return false;
		return super.canFinish();
	}

	private static interface Task
	{
		public void run(IProgressMonitor monitor,Shell shell)
			throws InvocationTargetException, InterruptedException;
	}
	private static class ShareProject implements Task
	{
		private IProject project;
		public ShareProject(IProject project)
		{
			this.project = project;
		}
		public void run(IProgressMonitor monitor, Shell shell)
			throws InvocationTargetException, InterruptedException
		{
			try 
			{
				monitor.beginTask("Share Project", 100);
				PerforceRepositoryProvider.setSharing(project, monitor);				
			} 
			catch(TeamException e) 
			{
				ErrorDialog.openError(shell, null, null, e.getStatus());
				throw new InvocationTargetException(e);
			}
		}		
	}
	private static class MoveProject implements Task
	{
		private IProject project;
		private IPath newLocation;
		public MoveProject(IProject project,IPath newLocation)
		{
			this.project = project;
			this.newLocation = newLocation;
		}
		public void run(IProgressMonitor monitor, Shell shell)
			throws InvocationTargetException, InterruptedException
		{
				try
				{
					monitor.beginTask("Move Project", 100);
					IProjectDescription description = project.getDescription();
					description.setLocation(newLocation);
					project.move(description,true,monitor);
				}
				catch (CoreException e)
				{
					ErrorDialog.openError(shell,null,null,e.getStatus());
					throw new InvocationTargetException(e);
				}
		}		
	}
	private List tasks = null;
	private void assembleTasks()
	{
		tasks = new ArrayList();

		String originalLoc = projectLocation();
		String newLoc = connectProjectPage.projectLocation().toString();
		if (! originalLoc.equals(newLoc))
			tasks.add(new MoveProject(project,connectProjectPage.projectLocation()));
		tasks.add(new ShareProject(project));
	}
	private void runTasks()
		throws InvocationTargetException,InterruptedException
	{
		getContainer().run(false, false, 
			new IRunnableWithProgress()
			{
				public void run(IProgressMonitor monitor)
					throws InvocationTargetException, InterruptedException
				{
					try 
					{
						for (Iterator i=tasks.iterator(); i.hasNext();)
						{
							Task task = (Task)i.next();
							task.run(monitor,(Shell)getContainer().getShell());
						}
					} 
					finally
					{
						monitor.done();
					}
				}
			});
	}
	/*
	 * @see IWizard#performFinish()
	 */
	public boolean performFinish()
	{
		try 
		{
			assembleTasks();
			if (tasks.size() > 0)
			{
				runTasks();
			}
	
		} 
		catch(InterruptedException e) 
		{
			e = e;
		}
		catch(InvocationTargetException e) 
		{
			Throwable target = e.getTargetException();
			
			if (target instanceof Error)
				throw (Error)target;
			else if (target instanceof RuntimeException)
				throw (RuntimeException)target;			
		} 
		
		return true;
	}

	/*
	 * @see IWizard#addPages()
	 */
	public void addPages()
	{
		connectProjectPage = new ConnectProjectPage(PerforceServerFactory.getPerforceServer(),MicroPluginFactory.getPlugin(),projectLocation()); 
		addPage(connectProjectPage);

/*
 * 		PerforceUtil.FolderRepositoryRelation relation = PerforceUtil.determineFolderPosition(project.getLocation().toFile().getAbsolutePath());
		
		if (relation == PerforceUtil.IN_VIEW)
		{
			autoconnectPage = ConfigurationWizardAutoconnectPage.newInstance("Connect Project to Depot");
			autoconnectPage.setProject(project);
			addPage(autoconnectPage);
			canConnect = true;
		}
		else if (relation == PerforceUtil.IN_REPOSITORY)
		{
			errorPage = new ErrorPage("Connect Project to Depot",
				"The project folder currently exists in your perforce repository. "
				+" Linking the project in your workspace to the existing repository folder"
				+" is dangerous.  If you wish to use the project that is in the repository"
				+" you should add it to your workspace from the Perforce Depot View. "
				); 
			addPage(errorPage);
			// @todo	Let them edit their view, and choose a new mapping for this project.
		}
		else if (relation == PerforceUtil.OUTSIDE_ROOT)
		{
			depotMappingPage = new MoveProjectPage(project.getLocation().toString()); 
			addPage(depotMappingPage);
			// @todo	Eventually, offer a way to create a new client
		}
		else if (relation == PerforceUtil.UNDER_ROOT)
		{
			changeViewPage = new SelectDepotPathPage("Connect Project to Deopt");
			addPage(changeViewPage);
			// Let them enter a depot-path - create another view in the current client
			// Incorporate a "depot-browser".
		}
		else
		{
			errorPage = new ErrorPage("Connect Project to Depot",
				"An unexpected error occurred communicating with the perforce depot.");
			addPage(errorPage);
			// @todo    Log Perforce behavior so we can track down problems, and show user
		}
*/
	}

	private String projectLocation() {
		return project.getLocation().toString();
	}

}
